package com.example.demo.exception;

import com.example.demo.utils.HttpCode;
import com.example.demo.utils.ResponseData;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
  * @Description: TODO
  * @author c10709
  * @date 2018/8/22 11:37
*/
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(UnsatisfiedServletRequestParameterException.class)
    public void handleException(HttpServletResponse response) throws IOException {
        response.sendError(HttpStatus.BAD_REQUEST.value());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseData handleBaseServiceException(Exception ex){
        if (ex instanceof MethodArgumentNotValidException) {
            final BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
            if (bindingResult.hasErrors()) {
                for (ObjectError allError : bindingResult.getAllErrors()) {
                    return ResponseData.failure(400, allError.getDefaultMessage());
                }
            } else {
                return ResponseData.failure(400, "参数校验出现未知异常！");
            }
        }
        if(ex instanceof MethodArgumentTypeMismatchException){
            return ResponseData.failure(400, "参数类型不匹配！");
        }
        if(ex instanceof BaseServiceException){
            Integer errorCode = ((BaseServiceException) ex).getErrorCode();
            LOGGER.error("code: "+ errorCode +" ,msg: "+ex.getMessage());
            return ResponseData.failure(errorCode, ex.getMessage());
        }
        //返回值700，用于前端做特殊处理
        if(ex instanceof LoginException){
            LOGGER.error("code: 700 ,msg: "+ex.getMessage());
            return ResponseData.failure(HttpCode.SPECIAL_ERROR.value(), ex.getMessage());
        }
        if (StringUtils.isBlank(ex.getMessage())) {
            //如果异常信息为空，则输出异常栈信息到logger，避免之前的GlobalExceptionHandler Line:54  - msg: null现象
            LOGGER.error("ERROR StackTrace:", ex);
            return ResponseData.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统异常，请联系管理员！");
        } else {
            LOGGER.error("msg: "+ex.getMessage());
        }
        return ResponseData.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getMessage());
    }


    @InitBinder
    public void initBinder(WebDataBinder binder) {
        /**
         * 自动转换日期类型的字段格式
         */
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), true));
        /**
         * 防止XSS攻击
         */
//        binder.registerCustomEditor(String.class,
//                new StringEscapeEditor(PropertiesUtil.getBoolean("spring.mvc.htmlEscape", false),
//                        PropertiesUtil.getBoolean("spring.mvc.javaScriptEscape", false)));
    }
}
